<template>
  <div>
    <input
      class="form-control"
      id="exampleInputEmail1"
      aria-describedby="emailHelp"
      :value="inputRef.val"
      @blur="validate"
      @input="updateValue"
      v-bind="$attrs"
    >
    <div id="emailHelp" class="form-text" v-if="inputRef.error">{{inputRef.message}}</div>
  </div>
</template>

<script lang='ts'>
/*
  实现自定义组件v-model
  第一步：props里面定义 modelValue
  第二步：发射自定义事件 update:modelValue
*/
import { defineComponent, reactive, PropType } from 'vue'
interface RuleProp {
  type: 'required' | 'email' | 'password',
  message: string
}
export type RulesProp = RuleProp[]
export default defineComponent({
  name: 'ValidateInput',
  // 不让组件的根元素继承 attribute
  inheritAttrs: false,
  props: {
    rules: {
      type: Array as PropType<RulesProp>
    },
    modelValue: {
      type: String
    }
  },
  setup (props, context) {
    const inputRef = reactive({
      val: props.modelValue || '',
      message: '',
      error: false
    })
    const emailReg = new RegExp('^[a-z0-9A-Z]+[- | a-z0-9A-Z . _]+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-z]{2,}$')
    const updateValue = (e: KeyboardEvent) => {
      const targetValue = (e.target as HTMLInputElement).value
      inputRef.val = targetValue
      context.emit('update:modelValue', targetValue)
    }
    const validate = () => {
      if (props.rules) {
        const allPass = props.rules.every(rule => {
          let passed = true
          inputRef.message = rule.message
          switch (rule.type) {
            case 'required':
              passed = inputRef.val.trim() !== ''
              break
            case 'email':
              passed = emailReg.test(inputRef.val)
              break
            case 'password':
              passed = inputRef.val.trim() !== ''
              break
            default:
              break
          }
          return passed
        })
        inputRef.error = !allPass
      }
    }
    return {
      inputRef,
      validate,
      updateValue
    }
  }
})
</script>

<style>

</style>
